home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / cmdline.lha / cmdline / src / lib / cmdline.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-04-13  |  8.3 KB  |  353 lines

  1. //------------------------------------------------------------------------
  2. // ^FILE: cmdline.c - implement CmdLine member functions.
  3. //
  4. // ^DESCRIPTION:
  5. //    Many of the more basic member functions of a CmdLine are implemented
  6. //    in this file. They are as follows:
  7. //
  8. //       Contructors
  9. //       Destructors
  10. //       CmdLine::name()
  11. //       CmdLine::error()
  12. //       CmdLine::append
  13. //
  14. // ^HISTORY:
  15. //    03/21/92    Brad Appleton    <brad@ssd.csd.harris.com>    Created
  16. //
  17. //    03/01/93    Brad Appleton    <brad@ssd.csd.harris.com>
  18. //    - Added cmd_nargs_parsed field to CmdLine
  19. //    - Added cmd_description field to CmdLine
  20. //    - Added exit_handler() and quit() member-functions to CmdLine
  21. //-^^---------------------------------------------------------------------
  22.  
  23. #include <stdlib.h>
  24. #include <iostream.h>
  25. #include <stdarg.h>
  26. #include <string.h>
  27. #include <ctype.h>
  28.  
  29. #include "cmdline.h"
  30. #include "cmdargs.h"
  31. #include "arglist.h"
  32. #include "states.h"
  33.  
  34. #define  va_CmdArgP(ap)  va_arg(ap, CmdArg *)
  35.  
  36.  
  37. //------------------------------------------------------------------- init_args
  38.  
  39. //-------------------
  40. // ^FUNCTION: init_args - initialize the arg_list member of a CmdLine
  41. //
  42. // ^SYNOPSIS:
  43. //    init_args(list)
  44. //
  45. // ^PARAMETERS:
  46. //    CmdArgListList & * list;
  47. //    -- a reference to the list that is to be initialized.
  48. //
  49. // ^DESCRIPTION:
  50. //    Allocate space for the list of command-arguments and insert
  51. //    The default arguments onto the list.
  52. //
  53. // ^REQUIREMENTS:
  54. //    list should be NULL upon entry
  55. //
  56. // ^SIDE-EFFECTS:
  57. //    creates the arg-list and makes "list" point to it.
  58. //
  59. // ^RETURN-VALUE:
  60. //    None.
  61. //
  62. // ^ALGORITHM:
  63. //    - Create a new arg-list (sure it is NOT self-cleaning, the user is
  64. //                             responsible for deleting inserted items)
  65. //    - Insert the default arguments onto the list
  66. //    - Make list point to the newly created list
  67. //-^^----------------
  68. static void
  69. init_args(CmdArgListList * & list)
  70. {
  71.    static  CmdArgUsage  default_help1('?', "?",    "; print usage and exit.");
  72.    static  CmdArgUsage  default_help2('H', "Help", "; print usage and exit.");
  73.  
  74.    list = new CmdArgListList ;
  75.    list->self_cleaning(1);
  76.  
  77.    CmdArgList * arg_list = new CmdArgList;
  78.    arg_list->self_cleaning(0);
  79.  
  80.    CmdArgList * default_list = new CmdArgList;
  81.    default_list->self_cleaning(0);
  82.    default_list->add(&default_help1);
  83.    default_list->add(&default_help2);
  84.  
  85.    list->add(arg_list);
  86.    list->add(default_list);
  87. }
  88.  
  89. //---------------------------------------------------------------- filebasename
  90.  
  91. //-------
  92. // ^FUNCTION: filebasename
  93. //
  94. // ^SYNOPSIS:
  95. //    static const char * filebasename(filename);
  96. //
  97. // ^PARAMETERS:
  98. //    const char * filename;
  99. //    -- the filename to get the "base" of.
  100. //
  101. // ^DESCRIPTION:
  102. //    Extract and return the basename of "filename".
  103. //
  104. // ^REQUIREMENTS:
  105. //    "filename" should be non-NULL and non-empty.
  106. //
  107. // ^SIDE-EFFECTS:
  108. //    On VAX/VMS, MS-DOS, and OS/2 systems space is allocated (using malloc)
  109. //    for the returned value.
  110. //
  111. // ^RETURN-VALUE:
  112. //    The basename portion of the filename.
  113. //
  114. // ^ALGORITHM:
  115. //    For Unix systems:
  116. //       return everything following the rightmost '/'
  117. //
  118. //    For VAX/VMS systems:
  119. //       make a copy of filename.
  120. //       strip off any device name, any directory name.
  121. //       strip off any "." extension.
  122. //       strip off any version number.
  123. //
  124. //    For MS-DOS systems:
  125. //       make a copy of filename.
  126. //       strip off any drive and/or directory path.
  127. //       strip off any "." extension.
  128. //-^^----
  129. static const char *
  130. filebasename(const char * filename)
  131. {
  132.  
  133. #if (defined(vms) || defined(msdos) || defined(os2))
  134.    const char * start, * p1, * p2 ;
  135.    char * str, * ext;
  136.  
  137. # ifdef vms
  138.    char * ver;
  139.    // remove leading directory and/or device name
  140.    p1 = ::strrchr(filename, ':');
  141.    p2 = ::strrchr(filename, ']');
  142. # else
  143.    // remove leading directory and/or drive name
  144.    p1 = ::strrchr(filename, '/');
  145.    p2 = ::strrchr(filename, '\\');
  146. # endif
  147.    if ((p1 == NULL) && (p2 == NULL)) {
  148.       start = filename ;
  149.    } else if (p1 && (p2 == NULL)) {
  150.       start = p1 + 1;
  151.    } else if (p2 && (p1 == NULL)) {
  152.       start = p2 + 1;
  153.    } else {
  154.       start = ((p1 > p2) ? p1 : p2) + 1;
  155.    }
  156.  
  157.    str = new char[strlen(start) + 1];
  158.    (void) ::strcpy(str, start);
  159.  
  160.    // remove the extension
  161.    ext = ::strrchr(str, '.');
  162.    if (ext)  *ext = '\0' ;
  163.  
  164. # ifdef vms
  165.    // remove the version
  166.    ver = ::strrchr(str, ';');
  167.    if (ver)  *ver = '\0' ;
  168. # endif
  169.  
  170.    return  str ;
  171.  
  172. #else
  173.  
  174.    char * p = ::strrchr(filename, '/') ;
  175.    return  (p == NULL) ? filename : (p + 1) ;
  176.  
  177. #endif /* if (vms || msdos || os2) */
  178.  
  179. }
  180.  
  181. //--------------------------------------------------------------- class CmdLine
  182.  
  183.   // Contructor with a command-name
  184. CmdLine::CmdLine(const char * cmdname)
  185.    : cmd_parse_state(cmd_START_STATE),
  186.      cmd_state(cmd_START_STATE),
  187.      cmd_flags(DEFAULT_CMDFLAGS),
  188.      cmd_status(CmdLine::NO_ERROR),
  189.      cmd_nargs_parsed(0),
  190.      cmd_name(NULL),
  191.      cmd_description(NULL),
  192.      cmd_matched_arg(NULL),
  193.      cmd_args(NULL),
  194.      cmd_err(NULL),
  195.      cmd_quit_handler(NULL)
  196. {
  197.    name(cmdname);
  198.    ::init_args(cmd_args);
  199. }
  200.  
  201.    // Constructor with a name and CmdArgs
  202. CmdLine::CmdLine(const char * cmdname, CmdArg * ...)
  203.    : cmd_parse_state(cmd_START_STATE),
  204.      cmd_state(cmd_START_STATE),
  205.      cmd_flags(DEFAULT_CMDFLAGS),
  206.      cmd_status(CmdLine::NO_ERROR),
  207.      cmd_nargs_parsed(0),
  208.      cmd_name(NULL),
  209.      cmd_description(NULL),
  210.      cmd_matched_arg(NULL),
  211.      cmd_args(NULL),
  212.      cmd_err(NULL),
  213.      cmd_quit_handler(NULL)
  214. {
  215.    name(cmdname);
  216.    ::init_args(cmd_args);
  217.  
  218.    CmdArgListListIter  iter(cmd_args);
  219.    CmdArgList * arg_list = iter();
  220.  
  221.    va_list  ap;
  222.    va_start(ap, cmdname);
  223.    for (CmdArg * cmdarg = va_CmdArgP(ap) ; cmdarg ; cmdarg = va_CmdArgP(ap)) {
  224.       arg_list->add(cmdarg);
  225.    }
  226.    va_end(ap);
  227. }
  228.  
  229.  
  230.    // Constructor with CmdArgs
  231. CmdLine::CmdLine(CmdArg * cmdarg, CmdArg * ...)
  232.    : cmd_parse_state(cmd_START_STATE),
  233.      cmd_state(cmd_START_STATE),
  234.      cmd_flags(DEFAULT_CMDFLAGS),
  235.      cmd_status(CmdLine::NO_ERROR),
  236.      cmd_nargs_parsed(0),
  237.      cmd_name(NULL),
  238.      cmd_description(NULL),
  239.      cmd_matched_arg(NULL),
  240.      cmd_args(NULL),
  241.      cmd_err(NULL),
  242.      cmd_quit_handler(NULL)
  243. {
  244.    if (cmdarg == NULL)  return;
  245.    ::init_args(cmd_args);
  246.  
  247.    CmdArgListListIter  iter(cmd_args);
  248.    CmdArgList * arg_list = iter();
  249.  
  250.    arg_list->add(cmdarg);
  251.  
  252.    va_list  ap;
  253.    va_start(ap, cmdarg);
  254.    for (cmdarg = va_CmdArgP(ap) ; cmdarg ; cmdarg = va_CmdArgP(ap)) {
  255.       arg_list->add(cmdarg);
  256.    }
  257.    va_end(ap);
  258. }
  259.  
  260.  
  261.    // Destructor
  262. CmdLine::~CmdLine(void)
  263. {
  264.    delete  cmd_args;
  265.  
  266. #if (defined(vms) || defined(msdos) || defined(os2))
  267.    delete [] cmd_name;
  268. #endif
  269. }
  270.  
  271.  
  272.    // Set the name of the command
  273. void
  274. CmdLine::name(const char * progname)
  275. {
  276. #if (defined(vms) || defined(msdos) || defined(os2))
  277.    delete [] cmd_name;
  278. #endif
  279.    cmd_name = ::filebasename(progname);
  280. }
  281.  
  282.  
  283.    // Print an error message prefix and return a reference to the
  284.    // error output stream for this command
  285. ostream &
  286. CmdLine::error(int  print) const
  287. {
  288.    ostream * os = (cmd_err) ? cmd_err : &cerr ;
  289.    if (print && cmd_name && *cmd_name)  *os << cmd_name << ": " ;
  290.    return  *os;
  291. }
  292.  
  293.  
  294.   // Add an argument to the current list of CmdArgs
  295. CmdLine &
  296. CmdLine::append(CmdArg * cmdarg)
  297. {
  298.    CmdArgListListIter  iter(cmd_args);
  299.    CmdArgList * arg_list = iter();
  300.    arg_list->add(cmdarg);
  301.  
  302.    return  *this ;
  303. }
  304.  
  305.    // terminate parsing altogether
  306. void
  307. CmdLine::quit(int status) {
  308.    if (cmd_quit_handler != NULL) {
  309.       (*cmd_quit_handler)(status);
  310.    } else {
  311.       ::exit(status);
  312.    }
  313. }
  314.  
  315. //---------------------------------------------------------- CmdLineCmdArgIter
  316.  
  317.    // Constructors and Destructors
  318.  
  319. CmdLineCmdArgIter::CmdLineCmdArgIter(CmdLine & cmd)
  320.    : iter(NULL)
  321. {
  322.    if (cmd.cmd_args) {
  323.       CmdArgListListIter  listlist_iter(cmd.cmd_args);
  324.       CmdArgList  * list = listlist_iter();
  325.       if (list)  iter = new CmdArgListIter(list);
  326.    }
  327. }
  328.  
  329. CmdLineCmdArgIter::CmdLineCmdArgIter(CmdLine * cmd)
  330.    : iter(NULL)
  331. {
  332.    if (cmd->cmd_args) {
  333.       CmdArgListListIter  listlist_iter(cmd->cmd_args);
  334.       CmdArgList  * list = listlist_iter();
  335.       if (list)  iter = new CmdArgListIter(list);
  336.    }
  337. }
  338.  
  339. CmdLineCmdArgIter::~CmdLineCmdArgIter(void)
  340. {
  341.    delete  iter;
  342. }
  343.  
  344.    // Return the current argument and advance to the next one.
  345.    // Returns NULL if we are already at the end of the list.
  346.    //
  347. CmdArg *
  348. CmdLineCmdArgIter::operator()(void)
  349. {
  350.    return  (iter) ? (*iter)() : NULL ;
  351. }
  352.  
  353.